package com.thinkit.cms.service.fragment;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.thinkit.cms.api.fragment.FragmentModelService;
import com.thinkit.cms.dto.fragment.FragmentModelDto;
import com.thinkit.cms.entity.fragment.FragmentModel;
import com.thinkit.cms.mapper.fragment.FragmentModelMapper;
import com.thinkit.core.base.BaseServiceImpl;
import com.thinkit.core.constant.Constants;
import com.thinkit.core.handler.CustomException;
import com.thinkit.nosql.annotation.CacheClear;
import com.thinkit.nosql.base.BaseRedisService;
import com.thinkit.utils.enums.BelongEnum;
import com.thinkit.utils.model.ApiResult;
import com.thinkit.utils.model.DynamicModel;
import com.thinkit.utils.utils.Checker;
import com.thinkit.utils.utils.ModelFieldUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 页面片段文件模型 服务实现类
 * </p>
 *
 * @author lg
 * @since 2020-08-02
 */
@Transactional
@Service
public class FragmentModelServiceImpl extends BaseServiceImpl<FragmentModelDto, FragmentModel, FragmentModelMapper> implements FragmentModelService {


    @Autowired
    BaseRedisService baseRedisService;

    @Transactional
    @CacheClear(method = "getMap",key = "#clas.targetClass+'.'+#clas.method+'.'+#p0.templateId")
    @Override
    public void createFile(FragmentModelDto v) {
        if(ckCode(v.getCode(),v.getTemplateId())){
            throw new CustomException(ApiResult.result(5027));
        }
        v.setId(id());
        String fileName =fileRename(v.getPath(),v.getRelativePath(),v.getId());
        v.setFileName(fileName);
        super.insert(v);
    }

    @CacheClear(method = "getMap",key = "#clas.targetClass+'.'+#clas.method+'.'+#p0")
    @Override
    public void deleteFile(String fragmentId) {
        if(Checker.BeNotBlank(fragmentId)){
            deleteByPk(fragmentId);
        }
    }


    @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p0",unless="#result == null")
    @Override
    public Map<String, String> getMap(String templateId) {
        Map<String, String> map =new HashMap<>();
        List<FragmentModelDto> fragmentModelDtos = baseMapper.fragmentModelByTempId(templateId);
        if(Checker.BeNotEmpty(fragmentModelDtos)){
            fragmentModelDtos.forEach(fragmentModelDto->{
                map.put(fragmentModelDto.getId(),fragmentModelDto.getAlias());
            });
        }
        return map;
    }

    @Override
    public FragmentModelDto getFragmentInfo(String fileName) {
        String id=getId(fileName);
        if(Checker.BeNotBlank(id)){
             FragmentModelDto fragmentModelDto= super.getByPk(id);
             if(Checker.BeBlank(fragmentModelDto.getDefaultFieldList())){
                 fragmentModelDto.setDefaultFieldList(JSONUtil.toJsonStr(ModelFieldUtil.loadModel(BelongEnum.FRAGMENT)));
             }
             return fragmentModelDto;
        }
        return null;
    }

    @CacheClear(method = "getMap",keys = {"#clas.targetClass+'.'+#clas.method+'.'+#p0.templateId",
    "#clas.targetClass+'.'+getFragmentFrom*"})
    @Override
    public void updateFragment(FragmentModelDto v) {
          ModelFieldUtil.filter(v);
          super.updateByPk(v);
    }

    @Override
    public  List<DynamicModel> getFragmentDesign(String fileName) {
        String id=getId(fileName);
        if(Checker.BeNotBlank(id)){
            String designStr =baseMapper.getFragmentDesign(id);
            if(Checker.BeNotBlank(designStr)){
                return ModelFieldUtil.jsonStrToModel(designStr);
            }
        }
        return Lists.newArrayList();
    }

    @Cacheable(value= Constants.cacheName, key="#root.targetClass+'.'+#root.methodName+'.'+#p0",unless="#result == null")
    @Override
    public Map<String, Object> getFragmentFrom(String fileName) {
        Map<String,Object> result =new HashMap<>();
        List<DynamicModel> models=getFragmentDesign(fileName);
        String id=getId(fileName);
        FragmentModelDto fragmentModelDto= baseMapper.getFragmentBaseByPk(id);
        result.put("models",models);
        result.put("data",fragmentModelDto);
        return result;
    }

    @Override
    public String getFragmentFieldListJsonStr(String id, Integer fieldType) {
        if(fieldType==0){
            return baseMapper.getFragmentDesign(id);
        } else if(fieldType ==1){
            return baseMapper.getFragmentExtendDesign(id);
        }
        return null;
    }

    @Override
    public String getFragmentPathByCode(String code) {
        return baseMapper.getFragmentPathByCode(code);
    }

    @Override
    public ApiResult getPartImport(String title) {
        title = Checker.BeNotBlank(title)?title.replace(Constants.DEFAULT_HTML_SUFFIX,""):null;
        if(Checker.BeNotNull(title)){
            String code =  baseMapper.getPartImport(title);
            if(Checker.BeNotBlank(code)){
                return ApiResult.result("<#include import('"+code+"')/>");
            }
            return ApiResult.result(5045);
        }
        return ApiResult.result(5045);
    }

    private String getId(String fileName){
        if(Checker.BeNotBlank(fileName)){
            String id =fileName.replace(Constants.DEFAULT_FRAGMENT_PREFIX,"").
                    replace(Constants.DEFAULT_HTML_SUFFIX,"");
            return id;
        }
        return "";
    }


    private boolean ckCode(String code,String templateId){
       return baseMapper.ckHasCode(code,templateId) >0;
    }

    private String fileRename(String path,String relativePath,String id){
         String fileName = Constants.DEFAULT_FRAGMENT_PREFIX+id;
         createFragment(path,fileName);
         String finalPath= relativePath+Constants.SEPARATOR+fileName+Constants.DEFAULT_HTML_SUFFIX;
         return finalPath.replace("\\","/");
    }

    private void createFragment(String path,String fileName){
        String realPath = path+ File.separator+fileName;
        if(isDirectory(path)){
            try {
                String filePath = realPath+ Constants.DEFAULT_HTML_SUFFIX;
                if(isFile(filePath)){
                    throw new CustomException(ApiResult.result(5025));
                }
                FileUtil.newFile(filePath).createNewFile();
            } catch (IOException e) {
                log.error("创建文件失败:"+e.getMessage());
            }
        }
    }

    private boolean isFile(String path){
        boolean isLegal = FileUtil.exist(path) && FileUtil.isFile(path);
        return isLegal;
    }


    private boolean isDirectory(String path){
        boolean isLegal = FileUtil.exist(path) && FileUtil.isDirectory(path) && Checker.BeNotBlank(path);
        return isLegal;
    }
}
